# Copyright (c) 2023 Presto Labs Pte. Ltd.
# Author: ziyan

import json
import toml
import itertools
import re

from absl import app
import os
from xunkemgmt_client.tool.slack_noti import send_to_slack


normal_enable_quote_list = ["USDT", "USD", "KRW", "EUR", "JPY", "GBP", "BUSD", "USDC", "TRY"]
briefing_str = ["Symbol Groups Update With PI\n",]

def extract_symbol_list_from_pi(mea):
  pi_path = 'data/coin2/product_info/{mea}.json'.format(mea=mea)
  if mea in ['Futures.Gateio.v4-btc', 'Futures.Gateio.v4']:
    pi_path = 'data/coin2/product_info/Futures.Gateio.v4.json'
  with open(pi_path, 'r') as f:
    pis = json.load(f)['product_infos']
  if mea in ['Futures.Gateio.v4-btc', 'Futures.Gateio.v4']:
    return separate_futures_Gateio_pi(mea, [pi['symbol'] for pi in pis])
  else:
    return [pi['symbol'] for pi in pis]


def separate_futures_Gateio_pi(mea, product_list):
  #Futures.Gateio.v4 and .v4-btc share one pi file
  if mea == 'Futures.Gateio.v4':
    return [pi for pi in product_list if re.match('.*-USD\.', pi) is None]
  else:
    return [pi for pi in product_list if re.match('.*-USD\.', pi) is not None]


def compare_symbol_groups_pi(mea):
  pi_symbol_list = extract_symbol_list_from_pi(mea)
  symbol_groups_symbol_list = list(itertools.chain.from_iterable(
      extract_symbol_group_dict_from_toml(mea).values()))
  enable_quote_list = normal_enable_quote_list
  if mea in ["Spot.Upbit.v1","Spot.Bithumb.v2","Spot.Coinone.v2","Spot.Korbit.v1"]:
    enable_quote_list = normal_enable_quote_list.copy()
    enable_quote_list.append("BTC")
  elif mea ==  "Spot.Upbitid.v1":
    enable_quote_list = normal_enable_quote_list.copy()
    enable_quote_list.append("BTC")
    enable_quote_list.append("IDR")
  elif mea == "Spot.Mercado.v4":
    enable_quote_list = normal_enable_quote_list.copy()
    enable_quote_list.append("BRL")

  def is_quote_enable(symbol):
    if symbol in symbol_groups_symbol_list:
      return False
    for quote in enable_quote_list:
      if re.match('.*-%s\..*$' % quote,symbol) is not None or re.match('.*-%s$' % quote,symbol) is not None :
        return True
    return False

  symbol_list_to_update = [symbol for symbol in pi_symbol_list if is_symbol_ok_update(mea,symbol) and is_quote_enable(symbol)]
  symbol_list_to_remove = [
    symbol for symbol in symbol_groups_symbol_list if symbol not in pi_symbol_list and is_symbol_ok_remove(symbol, mea)]  
  return symbol_list_to_update, symbol_list_to_remove


def is_symbol_ok_update(mea,symbol):
  if mea == 'Spot.Mexc.v2' or mea == 'Spot.Mexc.v3':
    if re.search(r'\d[S|L]-',symbol) is not None:
      return False
  elif mea == 'Spot.Gdax.v1':
    if 'USDC' in symbol:
      return False
  elif mea == 'Spot.Gateio.v4':
    if '-TRY' in symbol:
      return False
  return True

def is_symbol_ok_remove(symbol, mea):
  if 'MONTH' in symbol or 'QUARTER' in symbol or 'WEEK' in symbol:
    return False
  ico_path = "../coin_product_info/ico/%s.json" % mea
  if os.path.exists(ico_path) :
    with open(ico_path, 'r') as f:
      pis = json.load(f)
    for product_info in pis['product_infos']:
      if symbol == product_info['symbol']:
        return False
  if mea == "Futures.Prex.v1" and symbol in ["APE-USD.PERPETUAL", "GMT-USD.PERPETUAL", "IMX-USD.PERPETUAL", "RUNE-USD.PERPETUAL", "USDT-USD.PERPETUAL", "ETH2-USD.PERPETUAL"] :
    return False
  if mea == "Spot.Gateio.v4" and symbol in ["AMPL-USDT"]:
    return False
  return True

def get_symbol_group_dict_update(mea):
  symbol_group_dict = extract_symbol_group_dict_from_toml(mea)
  symbol_list_update_symbol_groups_pi, symbol_list_remove_symbol_groups_pi = compare_symbol_groups_pi(mea)
  symbol_list_to_update = list(set(symbol_list_update_symbol_groups_pi))

  for symbol in symbol_list_to_update:
    group = min(symbol_group_dict.keys(), key=(lambda k: len(symbol_group_dict[k])))
    symbol_group_dict[group].append(symbol)

  print_update_info(mea, symbol_list_to_update, [])
  return symbol_group_dict


def mea_to_mea_snake_string(mea):
  return mea.lower().replace('.', '_')


def extract_symbol_group_dict_from_toml(mea):
  symbol_groups_path = 'data/coin2/feed/symbol_groups.toml'
  with open(symbol_groups_path, 'r') as f:
    symbol_groups = toml.load(f)
    return symbol_groups[mea_to_mea_snake_string(mea)]


def update_symbol_groups_toml(mea, symbol_group_dict):
  symbol_groups_path = 'data/coin2/feed/symbol_groups.toml'
  with open(symbol_groups_path, 'r') as f:
    symbol_groups = toml.load(f)
    symbol_groups[mea_to_mea_snake_string(mea)] = symbol_group_dict
    if mea == 'Spot.Mexc.v3':
      symbol_groups['spot_mexc_v2'] = symbol_group_dict

  with open(symbol_groups_path, 'w') as f:
    toml.dump(symbol_groups, f)


def print_update_info(mea, symbol_list_to_update, symbol_list_to_remove):
  if len(symbol_list_to_update) <= 0 and len(symbol_list_to_remove) <= 0:
    return
  if mea == 'Spot.Mexc.v3':
    mea = 'Spot.Mexc.v2/v3'
  briefing_str.append(f"-------------------{mea}----------------- \n")
  if len(symbol_list_to_update) > 0:
    briefing_str.append("Add symbols: %s" % ",".join(symbol_list_to_update))
    briefing_str.append("\n")
  if len(symbol_list_to_remove) > 0:
    briefing_str.append("REMOVE symbols: %s" % ",".join(symbol_list_to_remove))
    briefing_str.append("\n")



def main(argv):
  meas = [
      'Spot.Bithumb.v2',
      'Spot.Upbit.v1',
      'Spot.Gdax.v1',
      'Spot.Bitstamp.v2',
      'Spot.Binance.v1',
      'Spot.Huobi.v1',
      'Futures.Binance.v1',
      'Futures.Binance.v1-delivery',
      'Futures.Huobi.v1',
      'Futures.Huobi.v1-swap',
      'Futures.Huobi.v1-linear-swap',
      'Futures.Bybit.v2',
      'Futures.Bybit.v2-linear',
      'Futures.Bybit.v3',
      'Futures.Bybit.v3-linear',
      'Futures.Bybit.v3-linear-usdc',
      'Spot.Korbit.v1',
      'Futures.Prex.v1',
      'Spot.Bybit.v1',
      'Spot.Bybit.v3',
      'Spot.Phemex.v1',
      'Spot.Okex.v5',
      'Futures.Okex.v5',
      'Futures.Okex.v5-swap',
      'Spot.Kucoin.v1',
      'Futures.Kucoin.v1',
      'Futures.Bitmex.v1',
      'Spot.Bitbank.v1',
      'Spot.Gateio.v4',
      'Futures.Gateio.v4',
      'Futures.Gateio.v4-btc',
      'Spot.Upbitid.v1',
      'Spot.Upbitsg.v1',
      'Spot.Mexc.v3',
      'Futures.Mexc.v1',
      'Spot.Binanceus.v1',
      'Spot.Crypto.v2',
      'Futures.Dydx.v3',
      'Spot.Btcturk.v1',
      'Futures.Phemex.v1',
      'Futures.Crypto.v1',
      'Futures.Apollox.v1',
      # 'Spot.Kraken.v1',
      # 'Spot.Bitget.v1',
      # 'Futures.Bitget.v1',
      # 'Spot.Mercado.v4',
      # 'Spot.Coingecko.v3',
      # 'Spot.Lbank.v2',
  ]

  for mea in meas:
      symbol_group_dict = get_symbol_group_dict_update(mea)
      update_symbol_groups_toml(mea, symbol_group_dict)
  if len(briefing_str) > 1:
    print("".join(briefing_str))
    send_to_slack("".join(briefing_str),'#hft_feed', 'file')

if __name__ == '__main__':
  app.run(main)
